/*
 * First Lastname, ID ********, Assignment 1
 */

/*
 * File: parts1.c
 *
 * This program uses a combination of File I/O and Structures to access
 * part data to keep track of inventory for a part dealer.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utils.h"
#include "parts1.h"

/* Note: The constant TOLERANCE is defined in this file to make it an 
 *       implementation detail specific to this application.
 */
#define TOLERANCE 1.0e-10

int main(void)
{
   Part part_list[MAX_PARTS];                 /* array of part records  */
   int num_records = 0;                       /* number of part records */
   char infile_name[] = "part_data.txt";      /* input file name        */
   char outfile_name[] = "part_matches.txt";  /* output file name       */
   double weight;                             /* weight entered by user */
   int compare_type;                          /* comparison type        */

   /* Read employee records from input file */
   FILE *in_fp = fopen(infile_name, "r");
   if (in_fp == NULL)
   {
      printf("Error: Could not open input file %s for reading.\n", infile_name);
      exit(EXIT_FAILURE);
   }
   while (!feof(in_fp))
   {
      part_list[num_records] = read_part_record(in_fp);
      num_records++;
   }
   num_records--;  /* to account for feof becoming true on attempt past end */
   fclose(in_fp);

   printf("\nThis program will find parts in the inventory based on a weight. You will have\na choice to get parts whose weight is less than, greater than, or equal to the\nweight you enter.\n");

   /* Get user's choice of weight */
   printf("\n");
   weight = get_double("Enter the weight to use for comparing with the parts' weights: ");

   /* Get user's choice of comparison to do */
   printf("\nComparison type:\n   1 - Find parts with weights LESS THAN your entered weight\n   2 - Find parts with weights EQUAL TO your entered weight\n   3 - Find parts with weights GREATER THAN your entered weight\n");
   printf("\n");
   compare_type = get_int("Enter the comparison type to use: ");
  
   /* Find matching parts and save them to output file */
   FILE *out_fp = fopen(outfile_name, "w");
   if (out_fp == NULL)
   {
      printf("Error: Could not open output file for writing.\n");
      exit(EXIT_FAILURE);
   }
   find_matching_parts(out_fp, weight, compare_type, part_list, num_records);
   fclose(out_fp);
   printf("\nA list of parts matching your selection has been saved in the file\n%s.\n\n", outfile_name);

   return 0;
}

/* The function read_part_record reads a single part record from the input file,
 * saves the data fields into a structure, and returns this structure.
 */
Part read_part_record(FILE *fp)
{
   Part new_part;               /* stores part data read from file      */
   char line[LINE_LENGTH];      /* current line of text being processed */

   /* Read a line of data from the file and divides it into fields */
   fgets(line, LINE_LENGTH, fp);
   rtrim(line);
   set_empty(new_part.pname, 25);
   sscanf(line, "%16c %s %lf %s %s %d", new_part.pname, new_part.pnumber, &new_part.weight, new_part.supplier1, new_part.supplier2, &new_part.in_stock);
   rtrim(new_part.pname);

   return new_part;
}

/* The function find_matching_parts searches the array of Part structures and
 * writes data from those with a matching weight to the output file.
 */
void find_matching_parts(FILE *fp, double weight, int compare_type, Part parts[], int number_records)
{
   int i;                   /* index for accessing array of structures */

   switch (compare_type)
   {
      case 1: for(i = 0; i < number_records; i++)
              {
                 if (parts[i].weight < weight)
                 {
                    fprintf(fp, "%s %s, %.2lf N, %d in stock\n", parts[i].pname, parts[i].pnumber, parts[i].weight, parts[i].in_stock);
                 }
              }
              break;
      case 2: for(i = 0; i < number_records; i++)
              {
                 /* condition uses idea of (parts[i].weight == weight) adjusted to include tolerance */
                 if (parts[i].weight > (weight - TOLERANCE) &&
                     parts[i].weight < (weight + TOLERANCE))
                 {
                    fprintf(fp, "%s %s, %.2lf N, %d in stock\n", parts[i].pname, parts[i].pnumber, parts[i].weight, parts[i].in_stock);
                 }
              }
              break;
      case 3: for(i = 0; i < number_records; i++)
              {
                 if (parts[i].weight > weight)
                 {
                    fprintf(fp, "%s %s, %.2lf N, %d in stock\n", parts[i].pname, parts[i].pnumber, parts[i].weight, parts[i].in_stock);
                 }
              }
              break;
   }
}

/* The function rtrim will remove white space characters from the end of a
 * string if there are any.
 */
void rtrim(char *str)
{
   char *end = str + strlen(str) - 1;    /* pointer to last char of string */
   while (*end == '\n' || *end == ' ' || *end == '\t')
   {
      *end = '\0';
      end--;
   }
}

/* The function set_empty will set all characters of a string to the null
 * character.
 */
void set_empty(char *str, int length)
{
   int i;        /* index for string */

   for (i = 0; i < length; i++)
   {
      str[i] = '\0';
   }
}
